package com.sync.utils.framework.interceptor;

import com.sync.utils.common.annotation.NotRepeatSubmit;
import com.sync.utils.common.enums.ResultCodeEnum;
import com.sync.utils.common.exception.BusinessException;
import com.sync.utils.common.utils.ApiUtil;
import com.sync.utils.common.utils.MD5Util;
import com.sync.utils.common.utils.StringUtil;
import com.sync.utils.framework.entity.AppInfo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.TimeUnit;


/**
 * 请求头参数校验
 *
 * @Author YWF
 * @Date 2022/1/25 15:09
 */
public class SignValidateInterceptor extends HeaderParamsCheckInterceptor {

    private final static Logger logger = LoggerFactory.getLogger(SignValidateInterceptor.class);

    @Override
    protected boolean signValidateHandle(HttpServletRequest request, Object handler, AppInfo appInfo, String timestamp, String nonce, String sign) {
        if (handler instanceof HandlerMethod){
            // 获取超时时间
            if (signEnabled){
                NotRepeatSubmit notRepeatSubmit = ApiUtil.getNotRepeatSubmit(handler);
                long expireTime = notRepeatSubmit == null ? REQUEST_OUT_TIME : notRepeatSubmit.value();

                // 2. 请求时间间隔
                logger.info("当前时间戳：{}",System.currentTimeMillis());
                logger.info("请求时间戳：{}",Long.valueOf(timestamp));
                long reqeustInterval = System.currentTimeMillis() - Long.valueOf(timestamp);
                logger.info("超时时间：{},过期时长：{}",reqeustInterval,expireTime);
                if (reqeustInterval > expireTime){
                    logger.info("超时时间：{},过期时间：{}",reqeustInterval,expireTime);
                    throw new BusinessException(ResultCodeEnum.REQUEST_TIME_OUT);
                }
                // 4. 校验签名(将所有的参数加进来，防止别人篡改参数) 所有参数看参数名升续排序拼接成url
                // 请求参数 + token + timestamp + nonce
                String appSecret = appInfo.getAppSecret();
                String signString = ApiUtil.concatSignString(request) + appSecret + timestamp + nonce;
                String signature = MD5Util.encode(signString);
                logger.info("signString:{},signature:{}",signString,signature);
                boolean flag = signature.equals(sign);
                if (!flag){
                    logger.info("用户签名：{}，系统签名：{}",sign,signature);
                    throw new BusinessException(ResultCodeEnum.SIGN_ERROR);
                }

                // 5. 拒绝重复调用(第一次访问时存储，过期时间和请求超时时间保持一致), 只有标注不允许重复提交注解的才会校验
                if (notRepeatSubmit != null){
                    boolean exists = redisCache.hasKey(sign);
                    if (exists){
                        throw new BusinessException(ResultCodeEnum.NO_REPEAT_REQUEST);
                    }
                    redisCache.set(sign, 0, expireTime, TimeUnit.MILLISECONDS);
                }
            }
        }
        return true;
    }


}
